home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / manchest.lha / MANCHESTER / manchester / 2.2 / Form-fromDigitizer.st < prev    next >
Text File  |  1993-07-24  |  7KB  |  191 lines

  1. "    NAME        Form-fromDigitizer
  2.     AUTHOR        Alan Wills <alan@cs.man.ac.uk>
  3.     FUNCTION     read in forms from simple digitizer array
  4.     ST-VERSIONS    
  5.     PREREQUISITES     
  6.     CONFLICTS    
  7.     DISTRIBUTION      world
  8.     VERSION        1.1
  9.     DATE    22 Jan 1989
  10. SUMMARY
  11. This stuff is for converting pictures from the CAT group's image digitizing equipment
  12. to a Form.  It's rather Manchester-local at the moment.  You need to use Granville Moore's
  13. software to dump the picture from the digitizer into a 512x512 array of ascii.  Then
  14. you use this to pick it up.
  15. See Form>>fromPic:level:range: for details.
  16.  
  17. alan@ux.cs.man.ac.uk"
  18.  
  19.  
  20. 'From Smalltalk-80, Version 2.2 of July 4, 1987 on 21 February 1988 at 6:07:22 pm'!
  21.  
  22.  
  23. !Array class methodsFor: 'instance creation'!
  24.  
  25. readPicFrom: fileName
  26.     "(Form extent: 128@128)
  27.         fromPic: (Array readPicFrom: '../image.saved') level: 31 range: 13;
  28.         displayOn: Display
  29.         at: 128@128 clippingBox: Display boundingBox
  30.         rule: Form over mask: Form black"
  31.  
  32.     "AlanPic _ Array readPicFrom: '../image.saved'"
  33.     "Answer a 512x512 Array with numbers initialized from 
  34.     the external file named fileName.  The file format is:
  35.         the image is always 512 x 512;
  36.         one character per pixel;
  37.         characters outside the range ' ' to ' '+63 should be ignored;
  38.         brightness is on a 6-bit scale, ' ' to ' '+63
  39.     "
  40.     | file m r c |
  41.     file _ FileStream oldFileNamed: fileName.
  42.     file readOnly.
  43.     m _ Array new: 512.
  44.     (1 to: 512) do: [:i| m at: 513 - i put: (r _ Array new:512).
  45.         (1 to: 512) do: [:j| 
  46.             [c _ file next asInteger. c<32] whileTrue: [].
  47.             r at: j put: c - 32 ]].
  48.     file close.
  49.     ^m! !
  50.  
  51. !Form methodsFor: 'printing'!
  52.  
  53. storeOn: aStream
  54.     "Append to the argument aStream a description of the receiver in the form:  
  55.             Form extent:fromCompactArray:#()offset:"
  56.     
  57.     "Some examples are
  58.      | s | s_ WriteStream on: (String new: 2000).
  59.     Form fromUser storeOn: s.
  60.     (Compiler evaluate: s contents) displayAt: 0@0.
  61.  
  62.      | f | f_ FileStream fileNamed: 'alan.form'.
  63.     Form fromUser storeOn: f.
  64.     f close. f size
  65.     "
  66.  
  67.     | stripe |
  68.     aStream nextPut: $(; nextPutAll: self species name; crtab: 1.
  69.     aStream nextPutAll: 'extent: '; print: self extent; crtab: 1.
  70.     aStream nextPutAll: 'fromCompactArray: #('.
  71.     1 to: height do: 
  72.         [:i |
  73.         stripe _ self scanLineStringAt: i-1.
  74.         stripe oldRunEncoded storeOn: aStream.
  75.         aStream cr].
  76.     aStream nextPut: $); crtab: 1.
  77.     aStream nextPutAll: 'offset: '; print: self offset; nextPut: $)! !
  78.  
  79. !Form methodsFor: 'initialize-release'!
  80.  
  81. fromPic: a level: level range: range
  82.     | r masks layers masksSize blackLevel contrast maskSorts jj jjj l targetSize targetScale sj tsTop tsBottom | 
  83.  
  84.     "takes a 512x512 Array of bytes and turns it into a Form.
  85.     The bytes represent variable brightness on a scale 0-63.
  86.     If the form is smaller than 512x512, the image is shrunk appropriately."
  87.  
  88.     "Display fromPic: AlanPic level: 31 range: 16."
  89.     "((Form extent: 256@256) bits: Display bits)
  90.         fromPic: AlanPic level: 30 range: 14"
  91.     "((Form extent: (Rectangle fromUserAspectRatio: 1@1) extent) bits: Display bits)
  92.         fromPic: AlanPic level: 30 range: 12"
  93.     "(Form extent: 128@128)
  94.         fromPic: (Array readPicFrom: '../image.saved') level: 31 range: 13;
  95.         displayOn: Display
  96.         at: 128@128 clippingBox: Display boundingBox
  97.         rule: Form over mask: Form black"
  98.     "ScheduledControllers background: fromUser"
  99.  
  100. "At each pixel, select the Form mask for the appropriate gray level.
  101. (Form white ... Form gray ... Form black in Form class>masks.) 
  102.  
  103. In large areas of all one brightness, the effect is to copy the mask onto the
  104. destination form.  In areas of varying brightness, the mask you copy from
  105. varies, but the effect is nevertheless as good as you could get by most
  106. methods.
  107.  
  108. (Remember that BitBlt always regards a mask as being fixed relative to the
  109. origin of the destination form: so you're picking up the pixel of the mask
  110. which is appropriate for that pixel on the destination for drawing that
  111. shade.)
  112.  
  113. The 'appropriate grey level' is done by some offset and scaling arithmetic
  114. on the levels given by the digitizer.
  115.  
  116. It's a bit slow to go through drawing each pixel by an individual call to
  117. BitBlt, so I make up a separate picture for each shade of grey (7 of them).
  118. Then I draw the pictures 'over' each other, each with its appropriate mask.
  119. I actually do this line by line, rather than doing the picture all in one
  120. lump: that way, if the target form is the Display, I can watch the picture
  121. being built up.  It takes about 4 minutes for a full-scale 512x512 picture.
  122.  
  123. For smaller scales, I sample the brightness at intervals.  This is better
  124. than scaling after the conversion using shrink or magnify: these methods
  125. only sample the binary pixels at intervals, which can have nasty
  126. interactions with the periods in the masks, and produce spurious lines and
  127. clumps.
  128.  
  129. There are one or two minimizations of the arithmetic done in the loop:
  130. rather than be converting between reals and integers a lot, I've used
  131. Fractions, separating the denominators and numerators so as to save time
  132. looking up coercions and finding gcds."
  133.     self extent > (512 @ 512)
  134.         ifTrue: [targetSize _ 512 @ 512. targetScale _ 1 asFraction]
  135.         ifFalse: [jj _ self extent x min: self extent y.
  136.                 targetSize _ jj @ jj. targetScale _ 512/jj ].
  137.     tsTop _ targetScale numerator. tsBottom _ targetScale denominator.
  138.     maskSorts _ #(black veryDarkGray darkGray gray lightGray veryLightGray white).
  139.     masksSize _ maskSorts size.
  140.     masks _ Array new: masksSize.
  141.     1 to: masksSize do: [:i| masks at: i put: (Form perform: (maskSorts at: i))].
  142.     blackLevel _ level - range.
  143.     contrast _ masksSize / (range * 2).
  144.  
  145.     layers _ Array new: masksSize.
  146.     (1 to: layers size) do: [:i| layers at: i put: (WordArray new: 512//16)].
  147.  
  148.     (1 to: targetSize y) do: [:i| r _ a at: (i * targetScale) asInteger.
  149.         jj _ 1. jjj _ 32768. layers do: [:layer| layer atAllPut: 0]. sj _ 0.
  150.  
  151. "and now the speed-critical loop:"
  152.         1 to: targetSize x do: [:j| sj _ sj + tsTop.
  153.             l _ layers at: ((((((r at: (sj quo: tsBottom))
  154.                              - blackLevel) asFraction * contrast)
  155.                              truncated) min: masksSize) max: 1).
  156.             l at: jj put: ((l at: jj) bitOr: jjj).
  157.             jjj <= 1 ifTrue: [jj _ jj + 1. jjj _ 32768] ifFalse: [ jjj _ jjj // 2]].
  158.  
  159.         self fill: (0 @ (i-1) extent: targetSize x @ 1)
  160.             rule: Form over
  161.             mask: Form white.
  162.         1 to: masksSize do: [:j|
  163.             self copyBits: (0@0 extent: targetSize x@1)
  164.                 from: (Form extent: 512 @1 fromArray: (layers at: j) offset: 0@0)
  165.                 at: 0 @ (i-1)
  166.                 clippingBox: self boundingBox
  167.                 rule: Form paint
  168.                 mask: (masks at: j)]
  169.         ].
  170.     ^self! !
  171.  
  172. Form organization classify: #storeOn: under: 'fileIn/Out' asSymbol!
  173.  
  174. Form organization classify: #storeOn:base: under: 'fileIn/Out' asSymbol!
  175.  
  176. Form organization removeCategory: #printing!
  177.  
  178. !Form class methodsFor: 'instance creation'!
  179.  
  180. fileInFrom: aFileName
  181.     "retrieve a form dumped by storeOn:"
  182.     "(Form fileInFrom: 'alan.form') displayOn: Display at: 0@0
  183.         clippingBox: Display boundingBox rule: Form over mask: Form black"
  184.     | file form | 
  185.     file _ FileStream oldFileNamed: aFileName.
  186.     form _ Compiler new evaluate: file in: nil to: nil notifying: nil ifFail: [].
  187.     ^ form! !
  188.  
  189. " r6 goodies 24/Feb/88
  190.  "
  191.